/*****************************************************************//**
 * \file   Command.h
 * \brief  获取命令行参数模块
 *
 * \author wangyingjie
 * \date   March 2025
 *********************************************************************/

#ifndef COMMAND_H
#define COMMAND_H

#define COMAND_SPACE ' '

#include "project_marco.h"

 /**
  * @class Command
  * @brief 获取命令行参数类
  */
class Command :public studio_singleton<Command>
{

public:
	// 用于存储命令的参数
	std::string trapezoid_name;
	double trapezoid_width;
	double trapezoid_height;
	double trapezoid_theta;

	std::string extrude_name;
	std::string extrude_source;
	double extrude_distance;

	bool is_show{ false };
	bool is_clear{ false };

public:

	/**
	 * @brief 获取命令参数中的配置文件路径
	 * @param argc 命令行参数个数
	 * @param argv 命令行参数数组
	 * @return 配置文件路径, 如果没有输入配置文件路径,或者输入的文件路径不存在,则返回空字符串
	 */
	std::string getConfigFilePath(const int& argc, char** argv)
	{
		std::string configFile;
		if (argc < 2)
		{
			std::string exeSelfName = argv[0];
			std::filesystem::path exeSelfPath(exeSelfName);
			std::string exeName = exeSelfPath.filename().string();
			std::string message = "Usage: " + exeName + "need input config file, example: " + exeName + " config.json";
			std::cout << message << std::endl;
			return std::string();
		}
		else
		{
			configFile = argv[1];
		}
		std::filesystem::path configPath(configFile);
		if (!std::filesystem::exists(configPath))
		{
			std::cout << "Config file does not exist: " << configFile << std::endl;
			return std::string();
		}
		return configPath.string();
	}

	/**
	 * @brief 获取命令行参数
	 * @param argc 命令行参数个数
	 * @param argv 命令行参数数组
	 * @return 是否成功获取命令行参数.
	 */
	bool getCommand(const int& argc, char** argv)
	{
		// 检查是否有输入命令
		if (argc < 2)
		{
			std::cout << "Invalid command, no command given." << std::endl;
			return false;
		}
		// 遍历每个命令
		for (int i = 1; i < argc; ++i)
		{
			std::string command = argv[i]; // 获取命令部分
			if (command == "trapezoid")
			{
				i++;  // 跳过命令部分
				std::unordered_map<std::string, std::string> params;
				while (i < argc && argv[i][0] == '-')
				{
					std::string param = argv[i];
					size_t equal_pos = param.find('=');
					if (equal_pos != std::string::npos)
					{
						std::string param_name = param.substr(1, equal_pos - 1);
						std::string param_value = param.substr(equal_pos + 1);
						params[param_name] = param_value;
					}
					++i;
				}
				if (!trapezoidCommand(params))
				{
					return false;
				}
				i--;
			}
			else if (command == "extrude")
			{
				i++;  // 跳过命令部分
				std::unordered_map<std::string, std::string> params;
				while (i < argc && argv[i][0] == '-')
				{
					std::string param = argv[i];
					size_t equal_pos = param.find('=');
					if (equal_pos != std::string::npos)
					{
						std::string param_name = param.substr(1, equal_pos - 1);
						std::string param_value = param.substr(equal_pos + 1);
						params[param_name] = param_value;
					}
					++i;
				}
				if (!extrudeCommand(params))
				{
					return false;
				}
				i--;
			}
			else if (command == "show")
			{
				std::cout << "Show command" << std::endl;
				is_show = true;
			}
			else if (command == "clear")
			{
				std::cout << "Clear command" << std::endl;
				is_clear = true;
			}
			else {
				std::cout << "Error: Invalid command: " << command << std::endl;
				return false;
			}
		}
		if (!is_clear && !is_show)
		{
			is_show = true;
			std::cout << "No command given , The default setting is show" << std::endl;
		}

		return true;
	}

	// trapezoid -name=2d_geometry -width=4 -height=2 -theta=30 
	// extrude -name=3d_geometry -source=2d_geometry -distance=0.5 show

	/**
	 * @brief 解析ui界面传过来的指令
	 * @param command 指令字符串
	 * @return 是否解析成功
	 */
	bool getUiCommand(const std::string& command)
	{
		bool status = false;
		std::vector<std::string> commands = studio_str_algo::separate(command, COMAND_SPACE);
		if (commands.size() < 1)
		{
			std::cout << "Invalid command, no command given." << std::endl;
			return status;
		}

		std::string cmd = commands[0];
		std::unordered_map<std::string, std::string> params;
		if (cmd == "trapezoid")
		{
			std::cout << "Trapezoid command" << std::endl;
			for (int i = 1; i < commands.size(); ++i)
			{
				std::string param = commands[i];
				if (param[0] == '-')
				{

					size_t equal_pos = param.find('=');
					if (equal_pos != std::string::npos)
					{
						std::string param_name = param.substr(1, equal_pos - 1);
						std::string param_value = param.substr(equal_pos + 1);
						params[param_name] = param_value;
					}
				}
			}
			if (!trapezoidCommand(params))
			{
				std::cout << "Error: Invalid trapezoid command" << std::endl;
				return status;
			}
		}
		else if (cmd == "extrude")
		{
			std::cout << "Extrude command" << std::endl;
			for (int i = 1; i < commands.size(); ++i)
			{
				std::string param = commands[i];
				if (param[0] == '-')
				{
					size_t equal_pos = param.find('=');
					if (equal_pos != std::string::npos)
					{
						std::string param_name = param.substr(1, equal_pos - 1);
						std::string param_value = param.substr(equal_pos + 1);
						params[param_name] = param_value;
					}
				}
			}
			if (!extrudeCommand(params))
			{
				std::cout << "Error: Invalid extrude command" << std::endl;
				return status;
			}
		}
		else if (command == "show")
		{
			std::cout << "Show command" << std::endl;
			is_show = true;
		}
		else if (command == "clear")
		{
			std::cout << "Clear command" << std::endl;
			is_clear = true;
		}
		else {
			std::cout << "Error: Invalid command: " << command << std::endl;
			return false;
		}

		status = true;
		return status;
	}



private:
	// 处理梯形参数
	bool trapezoidCommand(const std::unordered_map<std::string, std::string>& params)
	{
		bool status = false;
		if (params.find("name") != params.end())
		{
			trapezoid_name = params.at("name");
		}
		else
		{
			std::cout << "Error: Missing required parameter 'name' of 'trapezoid'" << std::endl;
			return status;
		}
		if (params.find("width") != params.end())
		{
			trapezoid_width = std::stod(params.at("width"));
		}
		else
		{
			std::cout << "Error: Missing required parameter 'width' of 'trapezoid'" << std::endl;
			return status;
		}
		if (params.find("height") != params.end())
		{
			trapezoid_height = std::stod(params.at("height"));
		}
		else
		{
			std::cout << "Error: Missing required parameter 'height' of 'trapezoid'" << std::endl;
			return status;
		}
		if (params.find("theta") != params.end())
		{
			trapezoid_theta = std::stod(params.at("theta"));
		}
		else
		{
			std::cout << "Error: Missing required parameter 'theta' of 'trapezoid'" << std::endl;
			return status;
		}
		status = true;

		std::cout << "Trapezoid :" << std::endl;
		std::cout << "\tName:" << trapezoid_name << "" << std::endl;
		std::cout << "\tWidth:" << trapezoid_width << "" << std::endl;
		std::cout << "\tHeight:" << trapezoid_height << "" << std::endl;
		std::cout << "\tTheta:" << trapezoid_theta << "" << std::endl;
		return status;
	}

	// 处理拉伸参数
	bool extrudeCommand(const std::unordered_map<std::string, std::string>& params)
	{
		bool status = false;
		if (params.find("name") != params.end())
		{
			extrude_name = params.at("name");
		}
		else
		{
			std::cout << "Error: Missing required parameter 'name' of 'extrude'" << std::endl;
			return	status;
		}
		if (params.find("source") != params.end())
		{
			extrude_source = params.at("source");
		}
		else
		{
			std::cout << "Error: Missing required parameter 'source' of 'extrude'" << std::endl;
			return	status;
		}
		if (params.find("distance") != params.end())
		{
			extrude_distance = std::stod(params.at("distance"));
		}
		else
		{
			std::cout << "Error: Missing required parameter 'distance' of 'extrude'" << std::endl;
			return	status;
		}
		status = true;

		std::cout << "Extrude:" << std::endl;
		std::cout << "\tName:" << extrude_name << "" << std::endl;
		std::cout << "\tSource:" << extrude_source << "" << std::endl;
		std::cout << "\tDistance:" << extrude_distance << "" << std::endl;
		return status;
	}
};



#endif //COMMAND_H
